/*
 * Copyright (c) 2023-2024 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.screw.query;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import javax.sql.DataSource;
import lombok.Getter;
import org.elsfs.cloud.common.util.lang.ExceptionUtils;
import org.elsfs.cloud.common.util.sql.DatabaseType;
import org.elsfs.cloud.common.util.sql.JdbcUtils;
import org.elsfs.cloud.screw.query.cachedb.CacheDbDataBaseQuery;
import org.elsfs.cloud.screw.query.db2.Db2DataBaseQuery;
import org.elsfs.cloud.screw.query.dm.DmDataBaseQuery;
import org.elsfs.cloud.screw.query.h2.H2DataBaseQuery;
import org.elsfs.cloud.screw.query.highgo.HigHgoDataBaseQuery;
import org.elsfs.cloud.screw.query.hsql.HsqlDataBaseQuery;
import org.elsfs.cloud.screw.query.mariadb.MariaDbDataBaseQuery;
import org.elsfs.cloud.screw.query.mysql.MySqlDataBaseQuery;
import org.elsfs.cloud.screw.query.oracle.OracleDataBaseQuery;
import org.elsfs.cloud.screw.query.phoenix.PhoenixDataBaseQuery;
import org.elsfs.cloud.screw.query.postgresql.PostgreSqlDataBaseQuery;
import org.elsfs.cloud.screw.query.sqlite.SqliteDataBaseQuery;
import org.elsfs.cloud.screw.query.sqlservice.SqlServerDataBaseQuery;

/**
 * 数据库查询工厂
 *
 * @author zeng
 */
@Getter
public class DatabaseQueryFactory implements Serializable {
  /** DataSource */
  private DataSource dataSource;

  /** 构造函数私有化 禁止通过new方式实例化对象 */
  private DatabaseQueryFactory() {}

  /**
   * 构造函数
   *
   * @param source {@link DataSource}
   */
  public DatabaseQueryFactory(DataSource source) {
    dataSource = source;
  }

  /**
   * 获取配置的数据库类型实例
   *
   * @return {@link DatabaseQuery} 数据库查询对象
   */
  public DatabaseQuery newInstance() {
    try {
      // 获取数据库URL 用于判断数据库类型
      String url = this.getDataSource().getConnection().getMetaData().getURL();
      // 获取实现类
      Class<? extends DatabaseQuery> query = getImplClass(JdbcUtils.getDbType(url));
      // 获取有参构造
      Constructor<? extends DatabaseQuery> constructor = query.getConstructor(DataSource.class);
      // 实例化
      return constructor.newInstance(dataSource);
    } catch (InstantiationException
        | IllegalAccessException
        | NoSuchMethodException
        | InvocationTargetException
        | SQLException e) {
      throw ExceptionUtils.mpe(e);
    }
  }

  /**
   * 根据连接地址判断数据库类型
   *
   * @param databaseType {@link DatabaseType} 连接地址
   * @return {@link DatabaseType} DatabaseType
   */
  @SuppressWarnings("AlibabaUndefineMagicConstant")
  public static Class<? extends DatabaseQuery> getImplClass(DatabaseType databaseType) {
    return switch (databaseType) {
      case MYSQL -> MySqlDataBaseQuery.class;
      case MARIADB -> MariaDbDataBaseQuery.class;
      case ORACLE -> OracleDataBaseQuery.class;
      case DB2 -> Db2DataBaseQuery.class;
      case H2 -> H2DataBaseQuery.class;
      case HSQL -> HsqlDataBaseQuery.class;
      case SQLITE -> SqliteDataBaseQuery.class;
      case POSTGRE_SQL -> PostgreSqlDataBaseQuery.class;
      case SQL_SERVER -> SqlServerDataBaseQuery.class;
      case SQL_SERVER2005 -> SqlServerDataBaseQuery.class;
      case DM -> DmDataBaseQuery.class;
      case HIGHGO -> HigHgoDataBaseQuery.class;
      case XU_GU -> OtherDataBaseQuery.class;
      case KINGBASE_ES -> OtherDataBaseQuery.class;
      case PHOENIX -> PhoenixDataBaseQuery.class;
      case CACHEDB -> CacheDbDataBaseQuery.class;
      case OTHER -> OtherDataBaseQuery.class;
    };
  }
}
